package com.eastfair.cloud.interceptor;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.eastfair.core.context.ContextConstants;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.utils.StrPool;
import com.eastfair.core.utils.StringUtils;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.List;

/**
 * feign client 拦截器， 实现将 feign 调用方的 请求头封装到 被调用方的请求头
 *
 * @author ligang
 * @date 2019-07-25 11:23
 */
@Slf4j
public class FeignAddHeaderRequestInterceptor implements RequestInterceptor {

    public static final List<String> HEADER_NAME_LIST = Arrays.asList(ContextConstants.JWT_KEY_USER_ID,
            ContextConstants.JWT_KEY_ACCOUNT, ContextConstants.JWT_KEY_NAME, ContextConstants.GRAY_VERSION,
            ContextConstants.LOG_TRACE_ID, ContextConstants.JWT_KEY_PROJECT_ID, ContextConstants.JWT_KEY_SUBSYSTEM_ID,
            ContextConstants.JWT_KEY_TEAM_ID, ContextConstants.EXHIBITION_ID, ContextConstants.LANGUAGE_TYPE, ContextConstants.TERMINAL_DEVICE, ContextConstants.TERMINAL_TYPE
            , ContextConstants.SUBJECT_TYPE, ContextConstants.JWT_KEY_REAL_NAME, ContextConstants.FEIGN
            , ContextConstants.MENU_SCENE, ContextConstants.SYSTEM_SCENE, ContextConstants.DATA_SCOPE_OF_USERID,
            ContextConstants.JWT_KEY_IS_ADMIN,
            ContextConstants.IS_SYSTEM_OLATION_IGNORE,ContextConstants.GATEWAY_RQUEST_URL,ContextConstants.GATEWAY_RQUEST_METHOD,
            ContextConstants.IS_IGNORE_URL
            , "X-Real-IP", "x-forwarded-for"
    );

    public FeignAddHeaderRequestInterceptor() {
        super();
    }

    @Override
    public void apply(RequestTemplate template) {
        template.header(ContextConstants.FEIGN, StrPool.TRUE);

        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null) {
            HEADER_NAME_LIST.forEach((headerName) -> {
                String str = ContextUtil.get(headerName);
                if (isChese(str)) {
                    try {
                        str = URLEncoder.encode(str, "UTF-8");
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                }
                log.info("---------------fegin  header params is {} value is {}", headerName, str);
                template.header(headerName, str);

            });
            return;
        }

        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        if (request == null) {
            log.warn("path={}, 在FeignClient API接口未配置FeignConfiguration类， 故而无法在远程调用时获取请求头中的参数!", template.path());
            return;
        }
        HEADER_NAME_LIST.forEach((headerName) -> {
            String header = request.getHeader(headerName);
            String contextStr = ContextUtil.get(headerName);
            //优先取上下文，再取header里信息
            contextStr = ObjectUtil.isEmpty(contextStr) ? header : contextStr;
            if (isChese(contextStr)) {
                try {
                    contextStr = URLEncoder.encode(contextStr, "UTF-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
            String value = ObjectUtil.isEmpty(contextStr) || isChese(contextStr) ? header : contextStr;
            log.info("---------------fegin  header params is {} value is {}", headerName, value);
            template.header(headerName, value);
        });
    }

    public boolean isChese(String str) {
        if (StringUtils.isBlank(str)) {
            return false;
        }
        for (char c : str.toCharArray()) {
            if (c >= 0x4E00 && c <= 0x9FA5) {
//                System.out.println("发现中文字符："+c);
                return true;
            }
        }
        return false;
    }

}
